package com.lihang.rabbit1.common.util;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lihang.rabbit1.common.exception.BusinessException;
import com.lihang.rabbit1.common.page.PageReq;
import com.lihang.rabbit1.common.page.PageRes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;

/**
 * Bean转换工具类
 * 用于实体类与DTO/VO之间的相互转换
 */
public class BeanConvertUtil {

    private static final Logger log = LoggerFactory.getLogger(BeanConvertUtil.class);

    /**
     * 将源对象转换为目标类型对象
     *
     * @param source      源对象
     * @param targetClass 目标类型
     * @param <S>         源类型
     * @param <T>         目标类型
     * @return 目标类型对象，若源对象为null则返回null
     */
    public static <S, T> T convert(S source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }

        try {
            T target = targetClass.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(source, target);
            return target;
        } catch (Exception e) {
            log.error("Bean转换异常: {} -> {}, 错误: {}", source.getClass().getName(), targetClass.getName(), e.getMessage(),
                    e);
            throw new BusinessException("Bean转换异常: " + e.getMessage());
        }
    }

    /**
     * 将源对象转换为目标类型对象
     *
     * @param source         源对象
     * @param targetSupplier 目标对象提供者
     * @param <S>            源类型
     * @param <T>            目标类型
     * @return 目标类型对象，若源对象为null则返回null
     */
    public static <S, T> T convert(S source, Supplier<T> targetSupplier) {
        if (source == null) {
            return null;
        }

        try {
            T target = targetSupplier.get();
            BeanUtils.copyProperties(source, target);
            return target;
        } catch (Exception e) {
            log.error("Bean转换异常: {} -> {}, 错误: {}", source.getClass().getName(),
                    targetSupplier.get().getClass().getName(), e.getMessage(), e);
            throw new BusinessException("Bean转换异常: " + e.getMessage());
        }
    }

    /**
     * 将源对象列表转换为目标类型对象列表
     *
     * @param sourceList  源对象列表
     * @param targetClass 目标类型
     * @param <S>         源类型
     * @param <T>         目标类型
     * @return 目标类型对象列表，若源列表为null则返回空列表
     */
    public static <S, T> List<T> convertList(Collection<S> sourceList, Class<T> targetClass) {
        if (sourceList == null || sourceList.isEmpty()) {
            return new ArrayList<>();
        }

        List<T> resultList = new ArrayList<>(sourceList.size());
        for (S source : sourceList) {
            try {
                resultList.add(convert(source, targetClass));
            } catch (Exception e) {
                log.error("列表转换异常: {} -> {}, 错误: {}",
                        source.getClass().getName(), targetClass.getName(), e.getMessage(), e);
            }
        }
        return resultList;
    }

    /**
     * 将源对象列表转换为目标类型对象列表
     *
     * @param sourceList     源对象列表
     * @param targetSupplier 目标对象提供者
     * @param <S>            源类型
     * @param <T>            目标类型
     * @return 目标类型对象列表，若源列表为null则返回空列表
     */
    public static <S, T> List<T> convertList(Collection<S> sourceList, Supplier<T> targetSupplier) {
        if (sourceList == null || sourceList.isEmpty()) {
            return new ArrayList<>();
        }

        List<T> resultList = new ArrayList<>(sourceList.size());
        for (S source : sourceList) {
            try {
                resultList.add(convert(source, targetSupplier));
            } catch (Exception e) {
                log.error("列表转换异常: {} -> {}, 错误: {}",
                        source.getClass().getName(), targetSupplier.get().getClass().getName(), e.getMessage(), e);
            }
        }
        return resultList;
    }

    /**
     * 将分页请求参数转换为目标类型的分页请求参数
     *
     * @param source      源分页请求对象
     * @param targetClass 目标分页请求类型
     * @param <S>         源类型
     * @param <T>         目标类型
     * @return 目标类型分页请求参数，若源对象为null则返回null
     */
    public static <S extends PageReq, T extends PageReq> T convertPageReq(S source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }

        try {
            T target = targetClass.getDeclaredConstructor().newInstance();
            // 复制分页基本属性
            target.setCurrentPage(source.getCurrentPage());
            target.setPageSize(source.getPageSize());
            target.setOrderField(source.getOrderField());
            target.setOrderType(source.getOrderType());

            // 复制子类特有属性
            BeanUtils.copyProperties(source, target);

            return target;
        } catch (Exception e) {
            log.error("分页请求参数转换异常: {} -> {}, 错误: {}",
                    source.getClass().getName(), targetClass.getName(), e.getMessage(), e);
            throw new BusinessException("分页请求参数转换异常: " + e.getMessage());
        }
    }

    /**
     * 将分页请求参数转换为目标类型的分页请求参数
     *
     * @param source         源分页请求对象
     * @param targetSupplier 目标分页请求对象提供者
     * @param <S>            源类型
     * @param <T>            目标类型
     * @return 目标类型分页请求参数，若源对象为null则返回null
     */
    public static <S extends PageReq, T extends PageReq> T convertPageReq(S source, Supplier<T> targetSupplier) {
        if (source == null) {
            return null;
        }

        try {
            T target = targetSupplier.get();
            // 复制分页基本属性
            target.setCurrentPage(source.getCurrentPage());
            target.setPageSize(source.getPageSize());
            target.setOrderField(source.getOrderField());
            target.setOrderType(source.getOrderType());

            // 复制子类特有属性
            BeanUtils.copyProperties(source, target);

            return target;
        } catch (Exception e) {
            log.error("分页请求参数转换异常: {} -> {}, 错误: {}",
                    source.getClass().getName(), targetSupplier.get().getClass().getName(), e.getMessage(), e);
            throw new BusinessException("分页请求参数转换异常: " + e.getMessage());
        }
    }

    /**
     * 将MyBatis Plus分页结果转换为自定义分页结果
     *
     * @param page        MyBatis Plus分页结果
     * @param targetClass 目标类型
     * @param <S>         源类型
     * @param <T>         目标类型
     * @return 自定义分页结果
     */
    public static <S, T> PageRes<T> convertPage(Page<S> page, Class<T> targetClass) {
        if (page == null) {
            return PageRes.empty();
        }

        PageRes<T> result = new PageRes<>();
        result.setTotal(page.getTotal());
        result.setPages(page.getPages());
        result.setCurrentPage(page.getCurrent());
        result.setPageSize(page.getSize());
        result.setHasPrevious(page.getCurrent() > 1);
        result.setHasNext(page.getCurrent() < page.getPages());

        // 转换记录列表，忽略转换失败的记录
        if (page.getRecords() != null && !page.getRecords().isEmpty()) {
            List<T> records = new ArrayList<>(page.getRecords().size());
            for (S source : page.getRecords()) {
                try {
                    records.add(convert(source, targetClass));
                } catch (Exception e) {
                    log.error("分页记录转换异常: {} -> {}, 错误: {}",
                            source.getClass().getName(), targetClass.getName(), e.getMessage(), e);
                }
            }
            result.setRecords(records);
        }

        return result;
    }

    /**
     * 将MyBatis Plus分页结果转换为自定义分页结果
     *
     * @param page           MyBatis Plus分页结果
     * @param targetSupplier 目标对象提供者
     * @param <S>            源类型
     * @param <T>            目标类型
     * @return 自定义分页结果
     */
    public static <S, T> PageRes<T> convertPage(Page<S> page, Supplier<T> targetSupplier) {
        if (page == null) {
            return PageRes.empty();
        }

        PageRes<T> result = new PageRes<>();
        result.setTotal(page.getTotal());
        result.setPages(page.getPages());
        result.setCurrentPage(page.getCurrent());
        result.setPageSize(page.getSize());
        result.setHasPrevious(page.getCurrent() > 1);
        result.setHasNext(page.getCurrent() < page.getPages());

        // 转换记录列表，忽略转换失败的记录
        if (page.getRecords() != null && !page.getRecords().isEmpty()) {
            List<T> records = new ArrayList<>(page.getRecords().size());
            for (S source : page.getRecords()) {
                try {
                    records.add(convert(source, targetSupplier));
                } catch (Exception e) {
                    log.error("分页记录转换异常: {} -> {}, 错误: {}",
                            source.getClass().getName(), targetSupplier.get().getClass().getName(), e.getMessage(), e);
                }
            }
            result.setRecords(records);
        }

        return result;
    }
}